package com.yugao.fintech.antelope.filepreview.service.impl;

import com.yugao.fintech.antelope.filepreview.config.ConfigConstants;
import com.yugao.fintech.antelope.filepreview.config.FileErrorEnum;
import com.yugao.fintech.antelope.filepreview.model.FileAttribute;
import com.yugao.fintech.antelope.filepreview.model.FilePreviewRS;
import com.yugao.fintech.antelope.filepreview.service.FileHandlerService;
import com.yugao.fintech.antelope.filepreview.service.FilePreview;
import com.yugao.fintech.antelope.filepreview.utils.AppFileUtils;
import com.yugao.fintech.antelope.filepreview.utils.DownloadUtils;
import com.yugao.fintech.antelope.filepreview.utils.EncodingDetects;
import com.yugao.fintech.framework.assistant.utils.exception.BizException;
import com.yugao.fintech.framework.core.response.Resp;
import com.yugao.fintech.framework.core.response.RetOps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import org.springframework.web.util.HtmlUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Objects;

/**
 * 处理文本文件
 */
@Slf4j
@Service
public class SimTextFilePreviewImpl implements FilePreview {
    private final FileHandlerService fileHandlerService;
    private final OtherFilePreviewImpl otherFilePreview;

    public SimTextFilePreviewImpl(FileHandlerService fileHandlerService, OtherFilePreviewImpl otherFilePreview) {
        this.fileHandlerService = fileHandlerService;
        this.otherFilePreview = otherFilePreview;
    }

    private static final String FILE_DIR = ConfigConstants.getFileDir();

    @Override
    public FilePreviewRS filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
        String fileName = fileAttribute.getName();
        String filePath = FILE_DIR + fileName;
        if (!fileHandlerService.listConvertedFiles().containsKey(fileName) || !ConfigConstants.isCacheEnabled()) {
            Resp<String> response = DownloadUtils.downLoad(fileAttribute, fileName);
            if (!RetOps.of(response).isSuccess()) {
                throw new BizException(response.getMsg());
            }
            filePath = response.getData();
            if (ConfigConstants.isCacheEnabled()) {
                fileHandlerService.addConvertedFile(fileName, filePath);  //加入缓存
            }
            try {
                String fileData = HtmlUtils.htmlEscape(Objects.requireNonNull(textData(filePath, fileName)));
                model.addAttribute("textData", Base64.encodeBase64String(fileData.getBytes()));
            } catch (IOException e) {
                log.error(e.getLocalizedMessage());
                throw new BizException(FileErrorEnum.FILE_NOT_SUPPORTED);
            }
            return FilePreviewRS.builder().type(TXT_FILE_PREVIEW_PAGE).build();
        }
        String fileData = null;
        try {
            fileData = HtmlUtils.htmlEscape(Objects.requireNonNull(textData(filePath, fileName)));
        } catch (IOException e) {
            e.printStackTrace();
        }
        model.addAttribute("textData", Base64.encodeBase64String(fileData.getBytes()));
        return FilePreviewRS.builder().type(TXT_FILE_PREVIEW_PAGE).build();
    }

    private String textData(String filePath, String fileName) throws IOException {
        File file = new File(filePath);
        if (AppFileUtils.isIllegalFileName(fileName)) {
            return null;
        }
        if (!file.exists() || file.length() == 0) {
            return "";
        } else {
            String charset = EncodingDetects.getJavaEncode(filePath);
            if ("ASCII".equals(charset)) {
                charset = StandardCharsets.US_ASCII.name();
            }
            BufferedReader br = new BufferedReader(new InputStreamReader(Files.newInputStream(Paths.get(filePath)), charset));
            StringBuilder result = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                result.append(line).append("\r\n");
            }
            br.close();
            return result.toString();
        }
    }
}
